home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-20 / pmpsrc11.zip / AX25DUMP.C < prev    next >
Text File  |  1991-07-30  |  9KB  |  426 lines

  1. /*
  2.     AX25DUMP.C -- Dumps AX.25 packets in human readable format
  3.  
  4.   Poor Man's Packet (PMP)
  5.   Copyright (c) 1991 by Andrew C. Payne    All Rights Reserved.
  6.  
  7.   Permission to use, copy, modify, and distribute this software and its
  8.   documentation without fee for NON-COMMERCIAL AMATEUR RADIO USE ONLY is hereby
  9.   granted, provided that the above copyright notice appear in all copies.
  10.   The author makes no representations about the suitability of this software
  11.   for any purpose.  It is provided "as is" without express or implied warranty.
  12.  
  13.     August, 1989
  14.     Andrew C. Payne
  15.  
  16.     09/13/89 - changed to work with L2 packet structures /acp/
  17. */
  18.  
  19. /* ----- Includes ----- */
  20. #include <stdio.h>
  21. #include <conio.h>
  22. #include <mem.h>
  23. #include <alloc.h>
  24. #include <string.h>
  25. #include "pmp.h"
  26. #ifdef NETROM
  27. #include "netrom.h"
  28. #endif
  29.  
  30. /* ----- Local Variables ----- */
  31. static    char ptext[1000];        /* packet text */
  32. static    char    *ploc;            /* current location in packet text */
  33.  
  34. /* cat(text)
  35.     Concatenates text string onto packet text string.
  36. */
  37. static void cat(char *p)
  38. {
  39.     while(*ploc++ = *p++)
  40.         ;
  41.     ploc--;
  42. }
  43.  
  44. /* ----- Level 1 to Level 2 conversion ----- */
  45.  
  46. /* AX25L1toL2(l1)
  47.     Given a pointer to a level 1 packet, converts it to a level 2 packet
  48.     structure and returns a pointer to the newly allocated level 2 packet
  49.     structure.
  50.  
  51.     Returns NULL if an error in the structure of the level 1 packet
  52. */
  53. struct ax25_packet *AX25L1toL2(struct ax25_level1 *p1)
  54. {
  55.     struct ax25_packet    p2;
  56.     struct ax25_packet    *p;
  57.     byte            *d;
  58.     byte            t1,t2;
  59.     int    cr[] = { UNKNOWN, RESPONSE, COMMAND, UNKNOWN };
  60.  
  61.     if(p1->len < 17)        /* no runt packets */
  62.         return NULL;
  63.  
  64.     d = p1->data;            /* packet data */
  65.  
  66. /* copy destination callsign and ssid */
  67.     memcpy(&p2.dest,d,MAXCLEN);
  68.     d += MAXCLEN;
  69.     p2.dest.ssid = SSIDMASK & (t1 = *d++);
  70.  
  71. /* copy source callsign and ssid */
  72.     memcpy(&p2.source,d,MAXCLEN);
  73.     d += MAXCLEN;
  74.     p2.source.ssid = SSIDMASK & (t2 = *d++);
  75.  
  76. /* command/response bits */
  77.     p2.cmdresp = cr[(((t1 & REPEATED) != 0) << 1) + ((t2 & REPEATED) != 0)];
  78.  
  79. /* copy digipeaters, if any */
  80.     p2.ndigis = 0;
  81.     while(p2.ndigis < MAXDIGIS && ((d[-1] & 1) == 0)) {
  82.         memcpy(&p2.digis[p2.ndigis],d,MAXCLEN);
  83.         d += MAXCLEN;
  84.         p2.digis[p2.ndigis].ssid = SSIDMASK & *d;
  85.         p2.repeated[p2.ndigis++] = REPEATED & *d++;
  86.     }
  87.  
  88.     if(p2.ndigis == MAXDIGIS)        /* too many digipeaters */
  89.         return NULL;
  90.  
  91. /* control field */
  92.     switch(FrameType(p2.cont = *d++)) {
  93.         case I:
  94.         case UI:
  95.             p2.pid = *d++;        /* protocol ID */
  96.     }
  97.  
  98. /* allocate record and copy in header and data field, if any */
  99.     p2.dlen = p1->len - (d - p1->data) - 2;    /* length remaining */
  100.     if(p2.dlen > 256 || p2.dlen < 0)
  101.         return NULL;            /* out of range packets */
  102.     p = malloc(sizeof(struct ax25_packet) + p2.dlen);
  103.     if(p == NULL)
  104.         return NULL;            /* out of memory */
  105.  
  106.     memcpy(p, &p2, sizeof(struct ax25_packet));
  107.     if(p2.dlen)
  108.         memcpy(p->data, d, p2.dlen);
  109.  
  110. /* return pointer to allocated packet */
  111.     return p;
  112. }
  113.  
  114. /* DumpLevel2Header(p)
  115.     Given a pointer to a Level 2 packet structure, creates a human readable
  116.     level 2 header and info field in ptext.
  117. */
  118. void DumpLevel2Header(struct ax25_packet *p)
  119. {
  120.     int    i;
  121.     int    showinfo;    /* flag for fields w/ info */
  122.     int    type;        /* frame type */
  123.     char    t[20];        /* temp space */
  124.  
  125.     ploc = ptext;
  126.  
  127. /* print the to/from address */
  128.     cat(GetAX25Addr(&p->source));
  129.     cat(">");
  130.     cat(GetAX25Addr(&p->dest));
  131.  
  132. /* print digipeaters */
  133.     if(p->ndigis) {
  134.         cat(" [via ");
  135.         for(i=0; i<p->ndigis; i++) {
  136.             cat(GetAX25Addr(p->digis + i));
  137.             if(p->repeated[i])
  138.                 cat("*");
  139.             if(i != (p->ndigis - 1))
  140.                 cat(",");
  141.         }
  142.         cat("]");
  143.     }
  144.  
  145. /* decode and show control byte */
  146.     cat("  <");
  147.     showinfo = FALSE;
  148.     switch(type = FrameType(p->cont)) {
  149.         case I:
  150.             cat("I");
  151.             showinfo = TRUE;
  152.             break;
  153.         case RR:
  154.             cat("RR");
  155.             break;
  156.         case RNR:
  157.             cat("RNR");
  158.             break;
  159.         case REJ:
  160.             cat("REJ");
  161.             break;
  162.         case SABM:
  163.             cat("SABM");
  164.             break;
  165.         case DISC:
  166.             cat("DISC");
  167.             break;
  168.         case DM:
  169.             cat("DM");
  170.             break;
  171.         case UA:
  172.             cat("UA");
  173.             break;
  174.         case FRMR:
  175.             cat("FRMR");
  176.             break;
  177.         case UI:
  178.             cat("UI");
  179.             showinfo = TRUE;
  180.             break;
  181.     }
  182.  
  183. /* show the protocol ID */
  184.     if(showinfo) {
  185.         switch(p->pid) {
  186.             case PID_TEXT:
  187.                 cat(" (Text)");
  188.                 break;
  189.             case PID_NETROM:
  190.                 cat(" (NET/ROM)");
  191.                 break;
  192.             default:
  193.                 sprintf(t," (PID=0x%X)",p->pid);
  194.                 cat(t);
  195.                 break;
  196.         }
  197.     }
  198.  
  199. /* show poll/final bit */
  200.     if(p->cont & PF) {
  201.         switch(p->cmdresp) {
  202.             case COMMAND:
  203.                 cat(" (P)");    /* cmd, poll */
  204.                 break;
  205.             case RESPONSE:
  206.                 cat(" (F)");    /* resp, final */
  207.                 break;
  208.             case UNKNOWN:
  209.                 cat(" (P/F)");
  210.                 break;
  211.         }
  212.     }
  213.  
  214. /* show sequence numbers */
  215.     if((type & 3) != U) {
  216.         sprintf(t," R%d",(p->cont >> 5) & 7);
  217.         cat(t);
  218.     }
  219.     if(type == I) {
  220.         sprintf(t," S%d",(p->cont >> 1) & 7);
  221.         cat(t);
  222.     }
  223.     cat(">");
  224. }
  225.  
  226. #ifdef NETROM
  227. /* ----- Net/Rom Packet Decoding ----- */
  228.  
  229. /* NRDumpBdcst(d)
  230.     Given a pointer to a broadcast data item, adds it to ptext.
  231. */
  232. static void NRDumpBdcst(struct nr_broadcast *p)
  233. {
  234.     char    t[80],t1[10],t2[10];
  235.  
  236. /* copy space padded alias */
  237.     memcpy(t1,p->alias,6);
  238.     t1[6] = '\0';
  239.  
  240. /* show routing entry */
  241.     strcpy(t2, GetAX25Addr(&p->neighbor));
  242.     sprintf(t,"%10s %10s    %10s %d\n",
  243.         GetAX25Addr(&p->dest),
  244.         t1,
  245.         t2,
  246.         p->quality);
  247.     cat(t);
  248. }
  249.  
  250. /* NetRomDump(d,len)
  251.     Given a Net/Rom packet, dumps it in human readable form (adds it to
  252.     ptext)
  253. */
  254. void NetRomDump(byte *d, int len)
  255. {
  256.     char    t[80],t1[10];
  257.     int    i;
  258.     int    data;
  259.  
  260.     if(len == 0)
  261.         return;
  262.  
  263.     data = FALSE;
  264.     cat(" NET/ROM: ");
  265. /* handle routing broadcasts */
  266.     if(*d == 0xff) {
  267.         d++;
  268.         len--;
  269.         cat("Routing for ");
  270.         memcpy(t,d,6);
  271.         d += 6;
  272.         len -= 6;
  273.         t[6] = 0;
  274.         cat(t);
  275.         cat("\n");
  276.         for(i=0; i<11; i++) {
  277.             if(len == 0)
  278.                 break;
  279.             NRDumpBdcst((struct nr_broadcast *)d);
  280.             d += sizeof(struct nr_broadcast);
  281.             len -= sizeof(struct nr_broadcast);
  282.         }
  283.         return;
  284.     }
  285.  
  286. /* decode network layer */
  287.     cat(GetAX25Addr(d));
  288.     cat(">");
  289.     cat(GetAX25Addr(d += sizeof(struct ax25_addr)));
  290.     d += sizeof(struct ax25_addr);
  291.     sprintf(t," (ttl=%u) ",*d++);
  292.     cat(t);
  293.     len -= (sizeof(struct ax25_addr) * 2 + 1);
  294.  
  295. /* decode transport layer */
  296.     switch(d[4] & 0x0f) {
  297.         case 0:
  298.             sprintf(t," Protocol %u, family %u",d[0],d[1]);
  299.             data = TRUE;
  300.             break;
  301.         case 1:
  302.             strcpy(t1, GetAX25Addr(d+6));
  303.             sprintf(t," Connect: %u/%u wnd %u %s@%s",
  304.                 d[0],d[1],d[5],
  305.                 t1,
  306.                 GetAX25Addr(d+6+sizeof(struct ax25_addr)));
  307.             break;
  308.         case 2:
  309.             sprintf(t," Connect ack: ur %u/%u, my %u/%u, wnd %u",
  310.                 d[0],d[1],d[2],d[3],d[5]);
  311.             break;
  312.         case 3:
  313.             sprintf(t," Disconnect: %u/%u",d[0],d[1]);
  314.             break;
  315.         case 4:
  316.             sprintf(t," Disconnect ack: %u/%u",d[0],d[1]);
  317.             break;
  318.         case 5:
  319.             sprintf(t," Info: %u/%u  txseq %u rxseq %u ::",
  320.                 d[0],d[1],d[2],d[3]);
  321.             data = TRUE;
  322.             break;
  323.         case 6:
  324.             sprintf(t," Info ack: %u/%u  txseq %u rxseq %u",
  325.                 d[0],d[1],d[2],d[3]);
  326.             break;
  327.         default:
  328.             sprintf(t," Unknown transport %u",d[4] & 0xf);
  329.             break;
  330.     }
  331.     cat(t);
  332.  
  333. /* copy in the data field, if any */
  334.     if(data) {
  335.         d += 5;
  336.         len -= 5;
  337.         cat("\n");
  338.         eol_in(EOL_CR, d, len);
  339.         while(len--) {        /* quick hack */
  340.             if(*d)
  341.                 *ploc++ = *d;
  342.             d++;
  343.         }
  344.     }
  345.     cat("\n");
  346. }
  347. #endif        /* Net/Rom */
  348.  
  349. /* ----- Packet Dump Routines ----- */
  350.  
  351. /* ShowLevel2(p)
  352.     Given a pointer to a level 2 packet, shows the packet on the screen.
  353.  
  354.     Munges packet data slightly (converts EOL).
  355. */
  356. void ShowLevel2(struct ax25_packet *p)
  357. {
  358. /* show the header */
  359.     DumpLevel2Header(p);
  360.     if(p->dlen)
  361.         cat(":\n");
  362.     else
  363.         cat("\n");
  364.     GotoLeft();
  365.     uputs(BrightAttr,ptext);
  366.  
  367. /* show the data field if any */
  368.     if(p->dlen) {
  369.         switch(p->pid) {
  370. #ifdef NETROM
  371.             case PID_NETROM:
  372.                 ploc = ptext;
  373.                 NetRomDump(p->data,p->dlen);
  374.                 uputs(NormalAttr,ptext);
  375.                 break;
  376. #endif
  377.             default:
  378.                 eol_in(EOL_CR, p->data, p->dlen);
  379.                 uputtext(NormalAttr,p->data,p->dlen);
  380.                 break;
  381.         }
  382.     }
  383.  
  384. /* make sure cursor is at column one */
  385.     GotoLeft();
  386. }
  387.  
  388. /* DumpLevel2(p)
  389.     Given a pointer to a level 2 packet, translates the packet into
  390.     human readable form and returns a pointer to the text string.
  391.  
  392.     (intended for file dump/log routines)
  393. */
  394. char *DumpLevel2(struct ax25_packet *p)
  395. {
  396.     byte    *data;
  397.     int    len;
  398.  
  399. /* decode header */
  400.     DumpLevel2Header(p);
  401.     if(p->dlen)
  402.         cat(":");
  403.  
  404. /* decode info field if any */
  405.     if(p->dlen) {
  406.         cat("\n");
  407.         switch(p->pid) {
  408.             case PID_TEXT:        /* copy in data, crude */
  409.                 len = p->dlen;
  410.                 data = p->data;
  411.                 while(len--)
  412.                     *ploc++ = *data++;
  413.                 break;
  414. #ifdef NETROM
  415.             case PID_NETROM:
  416.                 NetRomDump(p->data,p->dlen);
  417.                 break;
  418. #endif
  419.         }
  420.     }
  421.  
  422.     *ploc = '\0';        /* terminate */
  423.     return ptext;
  424. }
  425.  
  426.